#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <sys/time.h>
 
#include "data_type.h"
#include "cube.h"
#include "cube_define.h"
#include "cube_record.h"

#include "flag_verify.h"
#include "score_compute.h"

#include "score_event.h"
// add para lib_include

char Buf[DIGEST_SIZE*4];

static time_t max_time=2;

int score_event_init(void * sub_proc, void * para)
{
	int ret;
    	RECORD(SCORE_COMPUTE,ITEM_STATE) * item_state;

	RECORD(SCORE_COMPUTE,ITEM_STANDARD) * item_standard;
	item_standard=memdb_get_first_record(TYPE_PAIR(SCORE_COMPUTE,ITEM_STANDARD));
	while(item_standard != NULL)
	{
		item_state=Talloc0(sizeof(*item_state));
		if(item_state==NULL)
			return -ENOMEM;
		item_state->name = dup_str(item_standard->name,0);
		item_state->curr_score =item_standard->init_score;
		item_state->event_count =item_standard->event_num;
		memdb_store(item_state,TYPE_PAIR(SCORE_COMPUTE,ITEM_STATE),item_state->name);
		item_standard=memdb_get_next_record(TYPE_PAIR(SCORE_COMPUTE,ITEM_STANDARD));
	}
	return 0;
}

int score_event_start(void * sub_proc, void * para)
{
	int ret;
	void * recv_msg;
	int type;
	int subtype;
    	time_t curr_time;
    	time_t elapse_time;
	// add yorself's module exec func here
	while(1)
	{
		usleep(time_val.tv_usec);

		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
	    	if((type==TYPE(SCORE_COMPUTE))&&(subtype==SUBTYPE(SCORE_COMPUTE,EVENT)))
		{
			ret=proc_score_event_compute(sub_proc,recv_msg);
		}
	}
	return 0;
}

int compute_item_score(RECORD(SCORE_COMPUTE,ITEM_STATE) * item_state,RECORD(SCORE_COMPUTE,EVENT) * score_event,
    RECORD(SCORE_COMPUTE,EVENT_STANDARD) * event_standard,RECORD(GENERAL_RETURN,STRING) * audit_info)
{
    int ret=0;
    RECORD(SCORE_COMPUTE,ITEM_STANDARD) * item_standard;
    DB_RECORD  *db_record;
    switch(event_standard->event_type)
    {
        case SCORE_EVENT_START:
	    db_record = memdb_find_first(TYPE_PAIR(SCORE_COMPUTE,ITEM_STANDARD),
		"name",item_state->name);
	    if(db_record == NULL)
		return -EINVAL;
	    item_standard = db_record->record;
            item_state->curr_score=0;
            item_state->bonus_score=0;
            item_state->penalty_score=0;
	    item_state->event_count = item_standard->event_num;
            sprintf(Buf,"%s: %s",score_event->name,event_standard->desc);
            audit_info->name=dup_str(score_event->item_name,0);
            audit_info->return_value=dup_str(Buf,0);
            ret=1;
            break;
        case SCORE_EVENT_ADD:
            if(score_event->result == event_standard->result)
            {
                item_state->curr_score+=event_standard->score;
                sprintf(Buf,"%s: %s",score_event->name,event_standard->desc);
                audit_info->name=dup_str(score_event->item_name,0);
                audit_info->return_value=dup_str(Buf,0);
                ret=1;
            }
            break;
        case SCORE_EVENT_DEC:
            if(score_event->result == event_standard->result)
            {
                item_state->curr_score -= event_standard->score;
                sprintf(Buf,"%s: %s",score_event->name,event_standard->desc);
                audit_info->name=dup_str(score_event->item_name,0);
                audit_info->return_value=dup_str(Buf,0);
                ret=1;
            }
            break;
        case SCORE_EVENT_RESET:
            if(score_event->result == event_standard->result)
            {
                item_state->curr_score = 0;
                audit_info->name=dup_str(score_event->item_name,0);
                audit_info->return_value=dup_str(Buf,0);
                ret=1;
            }
            break;
        case SCORE_EVENT_OUTPUT:
            if(score_event->result == event_standard->result)
            {
	    	db_record = memdb_find_first(TYPE_PAIR(SCORE_COMPUTE,ITEM_STANDARD),
			"name",item_state->name);
	    	if(db_record == NULL)
			return -EINVAL;
	    	item_standard = db_record->record;
                if(item_state->curr_score <= item_standard->lowest_score)
			item_state->curr_score = item_standard->lowest_score;
		else if(item_state->curr_score >= item_standard->highest_score)
			item_state->curr_score = item_standard->highest_score;
                audit_info->name=dup_str(score_event->item_name,0);
                audit_info->return_value=dup_str(Buf,0);
                ret=1;
            }
            break;
        default:
            break;
    }

    return ret;
}

int proc_score_event_compute(void * sub_proc,void * recv_msg)
{
	int ret;
	RECORD(FLAG_VERIFY,SCORE) * flag_score;
	RECORD(SCORE_COMPUTE,EVENT) * score_event;
	RECORD(SCORE_COMPUTE,EVENT_STANDARD) * event_standard;
	RECORD(SCORE_COMPUTE,ITEM_STANDARD) * item_standard;
    	RECORD(SCORE_COMPUTE,ITEM_STATE) * verify_result;
    	RECORD(GENERAL_RETURN,STRING) * audit_info;
	BYTE uuid[DIGEST_SIZE];
	void * new_msg;
    	DB_RECORD * db_record;
	
	// get score_event from message
	ret=message_get_record(recv_msg,&score_event,0);
	if(score_event == NULL)
		return -EINVAL;
        // get verify result by find it from db with item_name
    	db_record=memdb_find_first(TYPE_PAIR(SCORE_COMPUTE,ITEM_STATE),"name",score_event->item_name);
    	if(db_record==NULL)
        	return -EINVAL;
	verify_result = db_record->record;

	// compute event's uuid
	memdb_comp_record_uuid(score_event,TYPE_PAIR(SCORE_COMPUTE,EVENT),uuid);

    	db_record=memdb_find(uuid,TYPE_PAIR(SCORE_COMPUTE,EVENT_STANDARD));
    	if(db_record==NULL)
        	return -EINVAL;
    
    	event_standard=db_record->record;
    	if(event_standard == NULL)
        	return -EINVAL;
   
    	audit_info = Talloc0(sizeof(*audit_info));
    	if(audit_info==NULL)
        	return -ENOMEM;
 
    ret=compute_item_score(verify_result,score_event,event_standard,audit_info);
    if(ret == 1) // valid score event
    {
	    verify_result->event_count--;
	    memdb_store(verify_result,TYPE_PAIR(SCORE_COMPUTE,ITEM_STATE),NULL);
            new_msg=message_create(TYPE_PAIR(GENERAL_RETURN,STRING),NULL);
            if(new_msg==NULL)
                 return -EINVAL;
            message_add_record(new_msg,audit_info);
            ex_module_sendmsg(sub_proc,new_msg);
	    print_cubeaudit("score_event:event count %d",verify_result->event_count);
            if((event_standard->event_type == SCORE_EVENT_OUTPUT)
			|| (verify_result->event_count<=0))
            {
                flag_score = Talloc0(sizeof(*flag_score));
                if(flag_score==NULL)
                    return -ENOMEM;
                flag_score->name=dup_str(verify_result->name,DIGEST_SIZE);
                flag_score->score=verify_result->curr_score;
                //flag_score->state=0;
                new_msg=message_create(TYPE_PAIR(FLAG_VERIFY,SCORE),NULL);
                if(new_msg==NULL)
                    return -EINVAL;
                message_add_record(new_msg,flag_score);
                ex_module_sendmsg(sub_proc,new_msg);
		// clear result
		//verify_result->curr_score=0;
		memdb_store(verify_result,TYPE_PAIR(SCORE_COMPUTE,ITEM_STATE),NULL);
            }
    } 
    return 0;
}
